#include <iostream>
using namespace std;
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <strings.h>
#include <functional>

namespace Server
{
    typedef function<void(int,string, uint16_t, string)> func_t;
    class udpServer
    {
    public:
        udpServer(const func_t &func, const uint16_t &port = 8080) :  _sock(-1),_callback(func), _port(port)
        {
        }

        void initServer()
        {
            _sock = socket(AF_INET, SOCK_DGRAM, 0); // 面向数据报
            if (_sock < 0)
            {
                perror("sock errno");
                exit(1);
            }
            printf("socket success\n");

            // 2:bind
            sockaddr_in local;
            bzero(&local, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;

            int ret = bind(_sock, (sockaddr *)&local, sizeof(local));
            if (ret < 0)
            {
                perror("bind errno");
                exit(1);
            }
            printf("bind success\n");
        }

        void start()
        {
            char buffer[1024];
            while (1)
            {
                sockaddr_in peer;
                bzero(&peer, sizeof(peer));
                socklen_t len = sizeof(peer);

                // 接收数据
                ssize_t n = recvfrom(_sock, buffer, sizeof(buffer) - 1, 0, (sockaddr *)&peer, &len);

                if (n > 0)
                {
                    buffer[n] = 0;
                    string clientip = inet_ntoa(peer.sin_addr);
                    uint16_t clientport = ntohs(peer.sin_port);
                    string message = buffer;
                    cout << clientip << "[" << clientport << "]#" << message << endl;
                    // 再把数据发回去
                    // my_to_upper(message); // 转为大写

                    // send(_sock, message.c_str(), message.size(), 0);

                    _callback(_sock,clientip, clientport, message);
                }
            }
        }

        ~udpServer()
        {
        }

    private:
        int _sock;
        uint16_t _port;

        func_t _callback;
    };
}